package com.aiowang.springboot.dynamic.activemq.starter;


import com.aiowang.springboot.dynamic.activemq.config.AMQCFFactory;
import com.aiowang.springboot.dynamic.activemq.config.DynamicActivemqProperties;
import com.aiowang.springboot.dynamic.activemq.listener.ActiveMQTransportListener;
import com.aiowang.springboot.dynamic.activemq.utils.ToolsUtils;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.connection.CachingConnectionFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @author aiowang
 * @date 2020-03-15 15:58
 */
@Configuration
public class DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor , EnvironmentAware {

    private Environment environment;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
    }


    /**
     * 先执行postProcessBeanDefinitionRegistry方法
     * 在执行postProcessBeanFactory方法
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
            throws BeansException {
        //绑定对象
       // ActivemqProperties propertiesC = Binder.get(environment).bind("spring.activemq", Bindable.of(ActivemqProperties.class)).get();
        //绑定Map
        Map<String,Object> propMap = new HashMap<>();
        String primary = "";
        try{
            propMap = Binder.get(environment).bind("spring.activemq.dynamic",Bindable.mapOf(String.class, Object.class)).get();
            for(Map.Entry<String, Object> entry : propMap.entrySet()){
                String mapKey = entry.getKey();
                if("primary".equals(mapKey)){
                    primary = (String)entry.getValue();
                    continue;
                }
                Object mapValue = entry.getValue();
                DynamicActivemqProperties dynamicActivemqProperties = ToolsUtils.mapToDAP(mapKey,(Map)mapValue);

                if(dynamicActivemqProperties.getSingle()){
                    ActiveMQConnectionFactory mqFactory = AMQCFFactory.createProduct(dynamicActivemqProperties);
                    mqFactory.setTransportListener(new ActiveMQTransportListener(mapKey));
                    BeanDefinitionBuilder a = BeanDefinitionBuilder.genericBeanDefinition(CachingConnectionFactory.class)
                            .addPropertyValue("targetConnectionFactory", mqFactory);

                    if(primary.equals(mapKey)){
                        a.setPrimary(true);
                    }
                    registry.registerBeanDefinition(mapKey, a.getBeanDefinition());

                    BeanDefinitionBuilder b = BeanDefinitionBuilder.genericBeanDefinition(DefaultJmsListenerContainerFactory.class)
                            .addPropertyValue("connectionFactory", registry.getBeanDefinition(mapKey))
                            .addPropertyValue("pubSubDomain", false);
                    registry.registerBeanDefinition(dynamicActivemqProperties.getQueueFactory(), b.getBeanDefinition());
                    BeanDefinitionBuilder c = BeanDefinitionBuilder.genericBeanDefinition(DefaultJmsListenerContainerFactory.class)
                            .addPropertyValue("connectionFactory", registry.getBeanDefinition(mapKey))
                            .addPropertyValue("pubSubDomain", true);
                    registry.registerBeanDefinition(dynamicActivemqProperties.getTopicFactory(), c.getBeanDefinition());


                }else{
                    ActiveMQConnectionFactory mqFactory = AMQCFFactory.createProduct(dynamicActivemqProperties);

                    BeanDefinitionBuilder a = BeanDefinitionBuilder.genericBeanDefinition(ActiveMQConnectionFactory.class)
                            .addPropertyValue("transportListener", new ActiveMQTransportListener(mapKey));
                    if(primary.equals(mapKey)){
                        a.setPrimary(true);
                    }
                    registry.registerBeanDefinition(mapKey, a.getBeanDefinition());
                    /*if(primary.equals(mapKey)){
                        registerBean(registry, mapKey, mqFactory.getClass(),true);
                    }else{
                        registerBean(registry, mapKey, mqFactory.getClass(),false);
                    }*/
                    BeanDefinitionBuilder b = BeanDefinitionBuilder.genericBeanDefinition(DefaultJmsListenerContainerFactory.class)
                            .addPropertyValue("connectionFactory", mqFactory)
                            .addPropertyValue("pubSubDomain", false);
                    registry.registerBeanDefinition(dynamicActivemqProperties.getQueueFactory(), b.getBeanDefinition());
                    BeanDefinitionBuilder c = BeanDefinitionBuilder.genericBeanDefinition(DefaultJmsListenerContainerFactory.class)
                            .addPropertyValue("connectionFactory", mqFactory)
                            .addPropertyValue("pubSubDomain", true);
                    registry.registerBeanDefinition(dynamicActivemqProperties.getTopicFactory(), c.getBeanDefinition());
                }

                System.out.println(mapKey+":"+mapValue);
            }


        }catch (Exception e){

        }


    }
    /**
     注册bean
     **/
    private void registerBean(BeanDefinitionRegistry registry, String name, Class<?> beanClass,Boolean isPrimary) {
        RootBeanDefinition bean = new RootBeanDefinition(beanClass);
        if(isPrimary){
            bean.setPrimary(true);
        }
        registry.registerBeanDefinition(name, bean);

    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
